package chapter3;

/**
 * public interface is used by who using your class
 * protected interface is used by who extending your class
 * @author wei
 *
 */
abstract class SortHarness {
    private Object[] values;
    private final SortMetrics curMetrics = new SortMetrics();
    
   /**
    * define the main flow and logic
    * @param data
    * @return
    */
    public final SortMetrics sort(Object[] data){
        values = data;
        curMetrics.init();
        doSort();
        return getMetrics();
    }
    
    public final SortMetrics getMetrics(){
        return curMetrics.clone();
    }
    
    /**
     * for extended classes to know the number of elements
     * @return
     */
    protected final int getDataLength(){
        return values.length;
    }
    
    /**
     * for extended classes to probe elements
     * @param i element index
     * @return
     */
    protected final Object probe(int i){
        curMetrics.probeCnt++;
        return values[i];
    }
    
    /**
     * for extended class to compare elements
     * @param i element index, not value self
     * @param j element index
     * @return
     */
    protected final int compare(int i, int j){
        curMetrics.compareCnt++;
        Object obj1 = values[i];
        Object obj2 = values[j];
        
        return doCompare(obj1, obj2);
    }
    
    /**
     * for extended classes to swap elements
     * @param i
     * @param j
     */
    protected final void swap(int i, int j){
        curMetrics.swapCnt++;
        Object tmp = values[i];
        values[i] = values[j];
        values[j] = tmp;
    }
    
    /**
     * extended classes implement this -- used by sort;
     * make it protected to force the test code to invoke it indirectly by the public sort method
     */
    protected abstract void doSort();
    
    protected abstract int doCompare(Object i, Object j);
}
